package com.baizhi.service.impl;

import com.baizhi.entity.Article;
import com.baizhi.service.ArticleService;
import com.baizhi.service.LuceneService;
import com.baizhi.utils.LuceneUtil;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.highlight.Highlighter;
import org.apache.lucene.search.highlight.InvalidTokenOffsetsException;
import org.apache.lucene.search.highlight.QueryScorer;
import org.apache.lucene.search.highlight.SimpleHTMLFormatter;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.wltea.analyzer.lucene.IKAnalyzer;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by 野马 on 2019/6/26.
 */
@Service
public class LuceneServiceImpl implements LuceneService {

    @Autowired
    private ArticleService articleService;

    /**
     * 添加一个document到索引库中
     */
    @Override
    public boolean addOneDocument(Article articlee) throws IOException {
        /**
         * 创建索引
         */

        List<Article> articleList = articleService.selectArticleAll(null);
        List<Document> list = new ArrayList<>();

        for (Article article : articleList) {
            Document document = new Document();
            document.add(new TextField("articleId",article.getArticleId().toString(), Field.Store.YES));
            document.add(new TextField("articleName",article.getArticleName(), Field.Store.YES));
            document.add(new StringField("articleContent",article.getArticleContent(), Field.Store.YES));
            list.add(document);
        }
        //要把索引存在哪里
        FSDirectory directory = FSDirectory.open(new File("E://lucenee"));
        //ik分词器
        IKAnalyzer ikAnalyzer = new IKAnalyzer();
        IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LUCENE_44,ikAnalyzer);
        IndexWriter indexWriter = new IndexWriter(directory,indexWriterConfig);

        /**
         *   addDocuments 把原始数据写出给对象
         *   indexWriter 会把原始数据写出到索引库  在写出的同时 indexWriter会自动扫苗原始数据创建索引
         */
        try {
            indexWriter.addDocuments(list);
            /**
             * 将索引提交到索引库
             */
            indexWriter.commit();
            return true;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            indexWriter.close();
        }
        return false;
    }

    /**
     * 创建索引库
     * 参数为要创建索引的数据
     * @return 成功返回true  失败返回false
     */

    @Override
    public boolean createIndex(List<Article> cmfzArticleList) {
        return false;
    }

    /**
     * 重置索引库  先删掉全部索引文件  再使用新的数据创建
     * 成功返回true  失败返回false
     * @return
     */

    @Override
    public boolean resetIndex(List<Article> cmfzArticleList) {
        return false;
    }

    /**
     * 删除索引库中全部文件
     *
     * @return 成功返回true  失败返回false
     */

    @Override
    public boolean deleteAllIndex() throws IOException {


        FSDirectory directory = FSDirectory.open(new File("E://lucenee"));
        IKAnalyzer analyzer = new IKAnalyzer();
        IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LUCENE_44,analyzer);
        IndexWriter indexWriter = new IndexWriter(directory,indexWriterConfig);

        try {
            indexWriter.deleteAll();
            indexWriter.commit();
            return true;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            indexWriter.close();
        }
        return false;
    }

    /**
     * 根据id删除索引库中对应的数据
     *
     * @return 成功返回true  失败返回false
     */

    @Override
    public boolean deleteIndexById(int articleId) {
        return false;
    }
    /**
     * 根据关键词检索  关键词可以是一个字儿  也可以是一句话
     * @param keyword
     * @return
     */

    @Override
    public List<Article> luceneSeleteByKeyword(String keyword) throws ParseException, IOException, InvalidTokenOffsetsException {
        //准备关键字
        //String keywork = "上师";

        //处理关键字
        String[] files = {"articleName","articleContent"};

        MultiFieldQueryParser queryParser = new MultiFieldQueryParser(Version.LUCENE_44,files,new IKAnalyzer());
        Query query = queryParser.parse(keyword);

        //用处理好的关键字查索引
        FSDirectory directory = FSDirectory.open(new File("E://lucenee"));
        DirectoryReader directoryReader = DirectoryReader.open(directory);
        IndexSearcher indexSearcher = new IndexSearcher(directoryReader);


        //4通过查到索引中的位置信息  获取数据
        TopDocs topDocs = indexSearcher.search(query,10);

        /**
         * 高亮展示
         * 1 创建一个高亮器
         * 参数1  高亮规则
         * 参数2  搜索词分词结果  QueryScorer  处理分词结果
         *
         * 将两个参数  给高梁器  高亮器 就会用高亮规则  处理关键次的分词结果
         * <font color='red'></font>
         */
        SimpleHTMLFormatter formatter = new SimpleHTMLFormatter("<font color='red'>","</font>");
        QueryScorer queryScorer = new QueryScorer(query);
        Highlighter highlighter = new Highlighter(formatter,queryScorer);


        ScoreDoc[] scoreDocs = topDocs.scoreDocs;

        List<Article> articList = new ArrayList<>();

        for(int i=0;i<scoreDocs.length;i++){
            ScoreDoc scoreDoc = scoreDocs[i];
            //获取Id
            int docId = scoreDoc.doc;
            //根据id查询Document对象
            Document document = indexSearcher.doc(docId);
            Article article = new Article();
            String articleId = document.get("articleId");
            String articleName = document.get("articleName");
            String articleContent = document.get("articleContent");


            articleName = highlighter.getBestFragment(new IKAnalyzer(),"articleName",articleName);
            articleContent = highlighter.getBestFragment(new IKAnalyzer(),"articleContent",articleContent);


            article.setArticleId(Integer.parseInt(articleId));
            article.setArticleName(articleName);
            article.setArticleContent(articleContent);
            articList.add(article);
        }
        return articList;
    }
}
